package mk.jug.academy.security;

import java.util.ArrayList;
import java.util.List;

import mk.jug.academy.service.AdministratorService;
import mk.jug.academy.service.LecturerService;
import mk.jug.academy.service.SponsorService;
import mk.jug.academy.service.StudentService;
import mk.jug.academy.service.SupporterService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.google.appengine.api.memcache.Expiration;
import com.google.appengine.api.memcache.MemcacheService;

/**
 * Implementation of the SpringSecurity {@link UserDetailsService}.
 *
 * @author Ice.Penov
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

	@Autowired private MemcacheService memcacheService;
	
	@Autowired private SponsorService sponsorService;
	@Autowired private SupporterService supporterService;
	@Autowired private StudentService studentService;
	@Autowired private LecturerService lecturerService;
	@Autowired private AdministratorService administratorService;
	
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		final List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
		mk.jug.academy.model.User user = (mk.jug.academy.model.User) memcacheService.get(username);		
		if (user == null) {
			//since polymorphic queries are not supported in GAE, we need to
			//look up different User entities separately...
			user = sponsorService.findByEmail(username);
			if (user == null) {
				user = supporterService.findByEmail(username);
				if (user == null) {
					user = studentService.findByEmail(username);
					if (user == null) {
						user = lecturerService.findByEmail(username);
						if (user == null) {
							user = administratorService.findByEmail(username);
						}
					}
				}
			}
			if (user == null) {
				return null;
			} else {
				memcacheService.put(username, user);
			}			
		}
		authorities.add(new GrantedAuthorityImpl("ROLE_" + user.getRole()));
		return new EnhancedUser(username, user.getPassword(), user.getSalt(), true, true, true, true, authorities);
	}

}